﻿// -------------------------------------------------------------------------------------------------------------------------------
// <copyright file="TestConstructor.cs" company="Exul">
//     Copyright (c) Exul. All rights reserved.
// </copyright>
// <author>
//     Exul
// </author>
// -------------------------------------------------------------------------------------------------------------------------------

namespace ExulLibrary.Mathematics.LinearAlgebra.Tests.CrcsSparseSymmetricMatrixTest
{
    #region Usings

    using System;

    using ExulLibrary.Exceptions;

    using NUnit.Framework;

    #endregion

    /// <summary>
    ///     Test suite for the constructor of <see cref="CrcsSparseSymmetricMatrix{T}"/>.
    /// </summary>
    [TestFixture]
    [Category("ExulLibrary.Mathematics.LinearAlgebra.CrcsSparseSymmetricMatrix{T}")]
    public sealed class TestConstructor
    {
        /// <summary>
        ///     Tests the constructor when all parameters have valid values and triangleData and diagonalData parameters
        ///     are <see langword="null"/>.
        /// </summary>
        [Test]
        public void WhenParametersAreValidWhenDataIsNull()
        {
            // Arrange
            // Matrix (1x1)
            var begins = new[] { 0, 1 };
            var indexes = new[] { 0 };

            // Act
            var matrix = new CrcsSparseSymmetricMatrix<object>(begins, indexes);

            // Assert
            Assert.That(matrix.RowsCount, Is.EqualTo(1));
            Assert.That(matrix.ColumnsCount, Is.EqualTo(1));
            Assert.That(matrix.IsSquare, Is.True);
            Assert.That(matrix.Begins, Is.SameAs(begins));
            Assert.That(matrix.Indexes, Is.SameAs(indexes));
            Assert.That(matrix.TriangleValues, Is.Not.Null & Has.Length.EqualTo(indexes.Length));
            Assert.That(matrix.DiagonalValues, Is.Not.Null & Has.Length.EqualTo(1));
        }

        /// <summary>
        ///     Tests the constructor when all parameters have valid values and
        ///     triangleData parameter is not <see langword="null"/>.
        /// </summary>
        [Test]
        public void WhenParametersAreValidWhenTriangleDataIsNotNull()
        {
            // Arrange
            var rowsBegins = new[] { 0, 1 };
            var columns = new[] { 0 };
            var triangleData = new object[1];

            // Act
            var matrix = new CrcsSparseSymmetricMatrix<object>(rowsBegins, columns, null, triangleData);

            // Assert
            Assert.That(matrix.RowsCount, Is.EqualTo(1));
            Assert.That(matrix.ColumnsCount, Is.EqualTo(1));
            Assert.That(matrix.IsSquare, Is.True);
            Assert.That(matrix.Begins, Is.SameAs(rowsBegins));
            Assert.That(matrix.Indexes, Is.SameAs(columns));
            Assert.That(matrix.TriangleValues, Is.SameAs(triangleData));
            Assert.That(matrix.DiagonalValues, Is.Not.Null & Has.Length.EqualTo(1));
        }

        /// <summary>
        ///     Tests the constructor when all parameters have valid values and
        ///     diagonalData parameter is not <see langword="null"/>.
        /// </summary>
        [Test]
        public void WhenParametersAreValidWhenDiagonalDataIsNotNull()
        {
            // Arrange
            var rowsBegins = new[] { 0, 1 };
            var columns = new[] { 0 };
            var diagonalData = new object[1];

            // Act
            var matrix = new CrcsSparseSymmetricMatrix<object>(rowsBegins, columns, diagonalData, null);

            // Assert
            Assert.That(matrix.RowsCount, Is.EqualTo(1));
            Assert.That(matrix.ColumnsCount, Is.EqualTo(1));
            Assert.That(matrix.IsSquare, Is.True);
            Assert.That(matrix.Begins, Is.SameAs(rowsBegins));
            Assert.That(matrix.Indexes, Is.SameAs(columns));
            Assert.That(matrix.TriangleValues, Is.Not.Null & Has.Length.EqualTo(1));
            Assert.That(matrix.DiagonalValues, Is.SameAs(diagonalData));
        }

        #if SAFE

        /// <summary>
        ///     Tests the constructor when begins parameter is <see langword="null"/>.
        /// </summary>
        [Test]
        public void WhenBeginsParameterIsNull()
        {
            // Arrange
            var indexes = new[] { 0 };

            // Act and Assert
            Assert.That(
                () => new CrcsSparseSymmetricMatrix<object>(null, indexes),
                Throws.TypeOf<ArgumentNullException>().With.Property("ParamName").EqualTo("begins"));
        }

        /// <summary>
        ///     Tests the constructor when begins parameter has less than two elements.
        /// </summary>
        [Test]
        public void WhenBeginsParameterHasNoEnoughElements()
        {
            // Arrange
            var begins = new[] { 0 };

            // length less than 2
            var indexes = new[] { 0 };

            // Act and Assert
            Assert.That(
                () => new CrcsSparseSymmetricMatrix<object>(begins, indexes),
                Throws.TypeOf<NoEnoughElementsException>().With.Property("ParamName").EqualTo("begins"));
        }

        /// <summary>
        ///     Tests the constructor when indexes parameter is <see langword="null"/>.
        /// </summary>
        [Test]
        public void WhenIndexesParameterIsNull()
        {
            // Arrange
            var begins = new[] { 0, 1 };

            // Act and Assert
            Assert.That(
                () => new CrcsSparseSymmetricMatrix<object>(begins, null),
                Throws.TypeOf<ArgumentNullException>().With.Property("ParamName").EqualTo("indexes"));
        }

        /// <summary>
        ///     Tests the constructor when indexes parameter has the number of elements less than
        ///     begins[rowsCount] - begins[0] parameter.
        /// </summary>
        [Test]
        public void WhenIndexesParameterHasNoEnoughElements()
        {
            // Arrange
            var begins = new[] { 0, 1 };

            // length  less than 1 - 0
            var indexes = new int[0];

            // Act and Assert
            Assert.That(
                () => new CrcsSparseSymmetricMatrix<object>(begins, indexes),
                Throws.TypeOf<NoEnoughElementsException>().With.Property("ParamName").EqualTo("indexes"));
        }

        /// <summary>
        ///     Tests the constructor when triangleData parameter is not <see langword="null"/> and
        ///     has the number of elements that less than begins[rowsCount] - begins[0].
        /// </summary>
        [Test]
        public void WhenTriangleDataParameterIsNotNullAndHasNoEnoughElements()
        {
            // Arrange
            var begins = new[] { 0, 1 };
            var indexes = new[] { 0 };

            // length less than 1 - 0
            var triangleData = new object[0];

            // Act and Assert
            Assert.That(
                () => new CrcsSparseSymmetricMatrix<object>(begins, indexes, null, triangleData),
                Throws.TypeOf<NoEnoughElementsException>().With.Property("ParamName").EqualTo("triangleData"));
        }

        /// <summary>
        ///     Tests the constructor when diagonalData parameter is not <see langword="null"/> and
        ///     has the number of elements that less than rows count.
        /// </summary>
        [Test]
        public void WhenDiagonalDataParameterIsNotNullAndHasNoEnoughElements()
        {
            // Arrange
            var begins = new[] { 0, 1 };
            var indexes = new[] { 0 };

            // length less than 1
            var diagonalData = new object[0];

            // Act and Assert
            Assert.That(
                () => new CrcsSparseSymmetricMatrix<object>(begins, indexes, diagonalData, null),
                Throws.TypeOf<NoEnoughElementsException>().With.Property("ParamName").EqualTo("diagonalData"));
        }

        #endif
    }
}